/* 2011/11/18 */
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.IO;
using System.Xml;

namespace Cosmos.Shortcuts
{ 
    /// <summary>
    /// A operation invoked by shortcut action.
    /// </summary>
    public struct ShortcutOperation
    {
        private int _operation;
        private string[] _arguments;

        /// <summary>
        /// Initialize a new instance of ShortcutOperation structure with specified operation code and arguments.
        /// </summary>
        /// <param name="operation">Operation code.</param>
        /// <param name="arguments">Arguments of operation.</param>
        public ShortcutOperation(int operation, params string[] arguments)
        {
            _operation = operation;
            _arguments = arguments;
            if (_arguments == null)
                _arguments = new string[0];
        }

        /// <summary>
        /// Initialize a new instance of ShortcutOperation structure by specified escape string.
        /// </summary>
        /// <param name="escapeString">Escape string of ShortcutOperation.</param>
        public ShortcutOperation(string escapeString)
            : this()
        {
            EscapeString = escapeString;
        }

        private string GenerateEscapeString()
        {
            StringWriter stringWriter = new StringWriter();
            XmlWriter xmlWriter = XmlWriter.Create(stringWriter, SimpleXmlSettings.WriterSettings);

            xmlWriter.WriteStartElement("Operation");
            xmlWriter.WriteString(_operation.ToString());
            xmlWriter.WriteEndElement();
            xmlWriter.WriteStartElement("Arguments");
            xmlWriter.WriteStartAttribute("Count");
            xmlWriter.WriteString(_arguments.Length.ToString());
            xmlWriter.WriteEndAttribute();
            foreach (string aParameter in _arguments)
            {
                xmlWriter.WriteStartElement("Value");
                xmlWriter.WriteString(aParameter);
                xmlWriter.WriteEndElement();
            }
            xmlWriter.WriteEndElement();

            xmlWriter.Flush();
            xmlWriter.Close();
            stringWriter.Flush();
            string result = stringWriter.ToString();
            stringWriter.Close();
            return result;
        }

        private void ParseEscapeString(string escapeString)
        {
            StringReader stringReader = new StringReader(escapeString);
            XmlReader xmlReader = XmlReader.Create(stringReader, SimpleXmlSettings.ReaderSettings);

            xmlReader.ReadStartElement("Operation");
            _operation = xmlReader.ReadContentAsInt();
            xmlReader.ReadEndElement();
            int argumentCount = Int32.Parse(xmlReader.GetAttribute("Count"));
            _arguments = new string[argumentCount];
            if (argumentCount > 0)
            {
                xmlReader.ReadStartElement("Arguments");
                for (int i = 0; i < argumentCount; i++)
                {
                    xmlReader.ReadStartElement("Value");
                    _arguments[i] = xmlReader.ReadContentAsString();
                    xmlReader.ReadEndElement();
                }
                xmlReader.ReadEndElement();
            }
            else
            {
                xmlReader.ReadStartElement("Arguments");
            }

            xmlReader.Close();
            stringReader.Close();
        }

        /// <summary>
        /// Gets or sets escape string of this instance of ShortcutOperation class.
        /// </summary>
        public string EscapeString
        {
            get { return GenerateEscapeString(); }
            set { ParseEscapeString(value); }
        }

        /// <summary>
        /// Gets or sets operation code of this instance of ShortcutOperation class.
        /// </summary>
        public int Operation 
        {
            get { return _operation; }
            set { _operation = value; } 
        }

        /// <summary>
        /// Gets or sets arguments of this instance of ShortcutOperation.
        /// </summary>
        public string[] Arguments
        { 
            get { return _arguments; }
            set { _arguments = value; } 
        }
    }

    /// <summary>
    /// A operation and its information.
    /// </summary>
    public struct ShortcutOperationInformation
    {
        private int _operation;
        private string _operationDescription;
        private int _parameterCount;
        private string _parameterDescription;

        public ShortcutOperationInformation(int operation, string operationDescription
            , int paramaterCount, string parameterDescription)
        {
            _operation = operation;
            _operationDescription = operationDescription;
            _parameterCount = paramaterCount;
            _parameterDescription = parameterDescription;
        }

        public ShortcutOperationInformation(int operation)
            : this(operation, null, 0, null)
        {

        }

        public ShortcutOperationInformation(int operation, string operationDescription, int parameterCount)
            : this(operation, operationDescription, parameterCount, null)
        {

        }

        public int Operation { get { return _operation; } }
        public string OperationDescription { get { return _operationDescription; } }
        public int ParamterCount { get { return _parameterCount; } }
        public string ParameterDescription { get { return _parameterDescription; } }
    }

    /// <summary>
    /// Collection of OperationInformation instances.
    /// </summary>
    public class OperationInformationCollection : IEnumerable<ShortcutOperationInformation>
    {
        private ShortcutOperationInformation[] _operations;

        public OperationInformationCollection(params ShortcutOperationInformation[] operations)
        {
            _operations = operations;
        }

        public IEnumerator<ShortcutOperationInformation> GetEnumerator()
        {
            foreach (ShortcutOperationInformation anOperation in _operations)
                yield return anOperation;
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}
